package org.example.util;

import org.example.otherObject.StringCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * 这个类用来处理敏感词的过滤
 */
@Component
public class SensitivityCodeFilter {
    private static StringCode root;
    private static String filterSymbol;
    private static final Logger logger = LoggerFactory.getLogger(SensitivityCodeFilter.class);
    //加载敏感官关键字
    static {
        String path = Thread.currentThread().getContextClassLoader().getResource("").getPath();
        File file = new File(path+"stringFilter.txt");
        FileInputStream fileInputStream = null;
        try {

            fileInputStream = new FileInputStream(file);
            byte[] bytes = new byte[(int)file.length()];
            fileInputStream.read(bytes);
            String temp = new String(bytes, StandardCharsets.UTF_8);
            String[] split = temp.split(",");
            root = new StringCode();
            for (String tempS : split){
                char[] chars = tempS.toCharArray();
                createTree(root, chars, 0);
            }
        } catch (Exception e) {
            logger.error(e.toString());
        }finally {
            if (fileInputStream!=null){
                try{
                    fileInputStream.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
    //加载过滤符号
    static {
        InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream("filterSymbol.txt");
        try {
            byte[] bytes = new byte[stream.available()];
            stream.read(bytes);
            filterSymbol = new String(bytes,StandardCharsets.UTF_8);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (stream!=null){
                try {
                    stream.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }

    }
    private static StringCode createTree(StringCode root,char[] array,int target){
        if (root == null) return null;
        if (array==null || array.length<=0 || target>=array.length) return root;
        char tempChar = array[target];
        Map<Character, StringCode> next = root.getNext();
        if (next.containsKey(tempChar)){
            //当前这一层包含了key 不能存储在这一层 下一层判定
            createTree(next.get(tempChar),array,target+1);
        }else {
            //可以创建节点了  但是需要判定节点是否为最后一个
            StringCode temp = new StringCode();
            temp.setCode(array[target]);
            if (target == array.length - 1){
                temp.setFoot(true);
            }
            next.put(array[target],temp);
            createTree(temp,array,target+1);
        }
        return root;
    }
    public void filter(StringBuilder str){
        innerFilter(root,root,str,0,0);
    }

    /**
     * 时间复杂度在O(n)-O(n^2)之间 好像啊 我也不清楚
     * @param root
     * @param changeCode
     * @param str
     * @param fast
     * @param slow
     */
    private void innerFilter(StringCode root,StringCode changeCode,StringBuilder str,int fast,int slow){
        if (str == null) return ;
        if (str.equals("") || str.equals(" ")) return ;
        if (fast>=str.length() || slow>=str.length()) return ;

        char[] chars = str.toString().toCharArray();
        char temp = chars[fast];
        Map<Character, StringCode> next = changeCode.getNext();
        if (next.containsKey(temp)){
            //当前节点存在key  需要判断是否是尾节点
            StringCode stringCode = next.get(temp);
            if (stringCode.isFoot()){
                //是尾节点  slow 和 fast 区间是一个敏感字 需要替换
                StringBuilder star = new StringBuilder();
                for (int i = slow;i<=fast;i++){
                    star.append('*');
                }
                str.replace(slow,(fast+1)>=str.length()?str.length():(fast+1), star.toString());
                //替换完毕 然后递归 ;
//                slow = ++fast;
                innerFilter(root,root,str,fast,slow);
            }else {
                //不是尾节点  需要下一层判定
                innerFilter(root,stringCode,str,++fast,slow);
            }
        }else {
            //当前节点不存在key  有一个问题 就是插入一个符号 喝%酒 这个也算  所以需要把符号过滤掉
            if (filterSymbol.contains(Character.toString(temp))){
                //这个是一个符号不能算数 跳过当前字符 下一个判断是否是敏感子
                innerFilter(root,changeCode,str,++fast,slow);
            }else {
                fast = ++slow;
                innerFilter(root,root,str,fast,slow);
            }

        }
    }
}
